package edu.fub.pub2search.db;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import edu.fub.pub2search.geo.GeoCalculator;
import edu.fub.pub2search.geo.GeoPosition;

/**
 * This class provides the filter to eliminate the pubs that are not inside
 * the searching radius.
 * 
 * @author Josef
 */
public class CircularRangeFilter {

	/** The central position of, e.g. a person */
	private GeoPosition centerPoint;
	
	/** The size of the radius */
	private double radius;
	
	/**
	 * The constructor.
	 * 
	 * @param latitude The latitude of the central position (in micro-degrees).
	 * @param longitude The longitude of the central position (in micro-degrees).
	 * @param radius The size of the radius.
	 */
	public CircularRangeFilter(int latitude, int longitude, double radius) {
		
		this(new GeoPosition(latitude, longitude), radius);
	}
	
	/**
	 * The constructor.
	 * 
	 * @param source The central position.
	 * @param radius The size of the radius.
	 */
	public CircularRangeFilter(GeoPosition centerPoint, double radius) {
		
		this.centerPoint = centerPoint;
		this.radius = radius;
	}
	
	/**
	 * Evaluate each record to satisfy the constraint of being inside the
	 * circle.
	 * 
	 * @param pointer The set of pub record.
	 * @return A list of pub record that inside the circle.
	 */
	public List<Map<String, String>> evaluate(ResultSet pointer) {
		
		// create the pub list.
		List<Map<String, String>> pubList = new ArrayList<Map<String, String>>();
		
		// this is for formating the time.
		SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
		
		try {
			// check for all records.
			while (pointer.next()) {
			
				// take the geo-position of each pub.
				int x = pointer.getInt(DataAccess.PUB_LATITUDE);
				int y = pointer.getInt(DataAccess.PUB_LONGITUDE);				
				GeoPosition testPoint = new GeoPosition(x, y);
				
				// calculate the distance of each pub.
				double distance = GeoCalculator.distance(centerPoint, testPoint);
				
				// check whether the distance is inside the circle
				boolean isInsideTheCircle = (distance <= radius)? true : false;
				
				// if yes!
				Map<String, String> pub;
				if (isInsideTheCircle) {
					
					// put the record put into a hash-map.
					pub = new HashMap<String, String>();
					
					pub.put("id", pointer.getString(DataAccess.PUB_ID));
					pub.put("name", pointer.getString(DataAccess.PUB_NAME));
					pub.put("address", pointer.getString(DataAccess.PUB_ADDRESS));
					pub.put("description", pointer.getString(DataAccess.PUB_DESCRIPTION));
					pub.put("facility", pointer.getString(DataAccess.PUB_FACILITY));
									
					Time time = pointer.getTime(DataAccess.PUB_OPEN_HOUR);
					pub.put("open_hour", new StringBuilder(timeFormat.format(time)).toString());
					
					time = pointer.getTime(DataAccess.PUB_CLOSE_HOUR);
					pub.put("close_hour", new StringBuilder(timeFormat.format(time)).toString());
					
					pub.put("latitude", Integer.toString(x));
					pub.put("longitude", Integer.toString(y));
					
					// populate to the pub list.
					pubList.add(pub);
				}
			}
			
			pointer.close(); // close the ResultSet object because we don't need it anymore.
			
		} catch (SQLException e) {
			
			e.printStackTrace();
		}
		
		return pubList;	
	}
}
